/*****************************************************************************
 * $Id: parser.h,v 1.35 2004/09/22 01:14:28 jimb Exp $
 * @file
 * @author  Jim Brooks http://www.jimbrooks.org
 *****************************************************************************/

#ifndef PARSER_H
#define PARSER_H

void
InitParser( void );

void
ParseFuncsInModule( char* ibuf, int ilen, char* pInputName );

/*----------------------------  PARSER_C  -------------------------------------*/

#ifdef PARSER_C

/*****************************************************************************
 * Change a char during preprocessing.
 *****************************************************************************/
#define PREPROC_CHANGE( CHAR )         *pc = CHAR;
#define PREPROC_CHANGE_NOT_EOL( CHAR ) if ( EX(*pc != '\n') ) *pc = CHAR;

/*****************************************************************************
 * Match a regex pattern.
 *****************************************************************************/
#define FIND_REGEX( PTR, LEN, HAYSTACK, RE )                         \
{                                                                    \
   static regmatch_t   pmatch[1];                                    \
   const int           eflags       = 0;                             \
   if ( EX(regexec( RE, HAYSTACK, 1, pmatch, eflags ) == 0) )        \
   {                                                                 \
      PTR = ((char*)HAYSTACK) + pmatch[0].rm_so;                     \
      LEN = pmatch[0].rm_eo - pmatch[0].rm_so;                       \
   }                                                                 \
   else                                                              \
   {                                                                 \
      PTR = NULL;                                                    \
      LEN = 0;                                                       \
   }                                                                 \
}

/*****************************************************************************
 * These macros are specific to the parser (the messages they print are).
 * Disable assertions in release for speed.
 *****************************************************************************/
#ifdef HYPERSRC_DEBUG
#   undef  ASSERT
#   define ASSERT(X) \
    if (UX(!(X))) { DebugMsg( "\n### assert(%s) failed in %s at line %d\n### parsing module '%s' near line %d\n", #X, __FILE__, __LINE__, pModuleName?pModuleName:"N/A", DebugGetLineCount() ); \
                    gtk_exit(1); }
#   undef  ASSERT_RETURN_VAL_IF_FAIL
#   define ASSERT_RETURN_VAL_IF_FAIL(X,VAL) \
    if (UX(!(X))) { DebugMsg( "\n### assert(%s) failed in %s at line %d\n### parsing module '%s' near line %d\n", #X, __FILE__, __LINE__, pModuleName?pModuleName:"N/A", DebugGetLineCount() ); \
                    return (VAL); }
#   undef  ASSERT_GOTO_IF_FAIL
#   define ASSERT_GOTO_IF_FAIL(X,LABEL) \
    if (UX(!(X))) { DebugMsg( "\n### assert(%s) failed in %s at line %d\n### parsing module '%s' near line %d\n", #X, __FILE__, __LINE__, pModuleName?pModuleName:"N/A", DebugGetLineCount() ); \
                    goto LABEL; }
#else
#   undef  ASSERT
#   define ASSERT( format, args... )
#   undef  ASSERT_RETURN_VAL_IF_FAIL
#   define ASSERT_RETURN_VAL_IF_FAIL(X,VAL) if (UX(!(X))) return (VAL);
#   undef  ASSERT_GOTO_IF_FAIL
#   define ASSERT_GOTO_IF_FAIL(X,LABEL) if (UX(!(X))) goto LABEL;
#   undef  g_assert
#   define g_assert( format, args... )
#   undef  g_assert_return_val_if_fail
#   define g_assert_return_val_if_fail( format, args... )
#endif

struct lineCount_t
{
   int   cnt;   /* line count */
   char* buf;   /* beginning of buffer */
   int   len;   /* length of buffer */
   char* cur;   /* current position within buffer */
};

typedef char* (*parseEveryCallback_t)( int* pMatchLen/*OUT*/, char* ibuf, int ilen, struct lineCount_t* lc );

static void
ParseModule( char* ibuf, int ilen );

static void
Preprocess( char* ibuf, int ilen );

static void
ParseEvery( char* ibuf, int ilen, parseEveryCallback_t callback );

static char*
ParseFuncDef( int* pMatchLen/*OUT*/, char* ibuf, int ilen, struct lineCount_t* lc );

static char*
ParseFuncDef2( int*   pFuncDefLen,  /*OUT*/
               char** ppFuncId,     /*OUT*/
               int*   pFuncIdLen,   /*OUT*/
               char** ppLeftBrace,  /*OUT*/
               char** ppRightBrace, /*OUT*/
               char*  ibuf,
               int    ilen );

static char*
ParseClassInlines( int* pMatchLen/*OUT*/, char* ibuf, int ilen, struct lineCount_t* lc );

static char*
ParseClassInlines_Part1( int* pMatchLen/*OUT*/, char* ibuf );

static void
ParseFuncCalls( char* ibuf, int ilen );

static void
ParseAddFuncDefToGraph( char* pFuncId, int funcIdLen, int lineFirst, int lineFinal );

static gboolean
IfFirstLineOfFuncDef( char* pLeftParenthesis, char* ibuf );

static char*
ScanBackwardsForFuncId( int* pFuncIdLen/*OUT*/, char* pRightParenthesis, char* ibuf );

static void
ResetLineCount( struct lineCount_t* lc, char* buf, int len );
#if 0
static void
SetLineCount( struct lineCount_t* lc, int cnt, char* cur );
#endif
static int
UpdateLineCount( struct lineCount_t* lc, char* cur );

#ifdef HYPERSRC_DEBUG
static int
DebugGetLineCount( void );
#endif

#endif /* PARSER_C */

/*----------------------------  PARSER_C  -------------------------------------*/

#endif /* PARSER_H */
